<?php
namespace Core\CoreComponents\DocumentsManager;
use Core;
/**
* This class provide all method to work with a file or a folder
*
* @method ServiceResponse GetFiles($dir, &$dir_array)
* @method ServiceResponse GetCountFiles($dir)
* @method ServiceResponse GetFilesToDocuments($dir, &$documents, $parent = null)
* @method ServiceResponse GetFolders($rootPath, &$dir_array)
* @method ServiceResponse Upload($tempPath, $dirPath, $filename)
* @method ServiceResponse Delete($path)
* @method ServiceResponse deleteDirectory($dir) 
* @method ServiceResponse Rename($path, $newName, $oldName)
* @method ServiceResponse Copy($src, $dst)
* @method ServiceResponse CreateDirectory($path)
*/
class FileSystemHelpers
{
	/**
	 * Recursive function to return a multidimensional array of folders and files
	 *
	 * @param string $dir The directory path
	 * @param array $dir_array The array directories
	 * 
	 * @return A multidimensional array of folders and files
	 */
	public function GetFiles($dir, &$dir_array)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - GetFiles from $dir");
		
		// Create array of current directory
		$files = preg_grep('/^([^.])/', scandir($dir));
	    
		if(is_array($files))
		{
			foreach($files as $val)
			{
				// Skip home and previous listings
				if($val == '.' || $val == '..')
					continue;
			   
				// If directory then dive deeper, else add file to directory key
				if(is_dir($dir.'/'.$val))
				{
					// Add value to current array, dir or file
					$dir_array[$dir][] = $val;

					$this->GetFiles($dir.'/'.$val, $dir_array);
				}
				else
				{
					$dir_array[$dir][] = $val;
				}
			}
		}
		ksort($dir_array);
	}
	
	/**
	 * Recursive function to return a number of files found in the path 
	 *
	 * @param string $dir The directory path
	 * 
	 * @return A multidimensional array of folders and files
	 */
	public function GetCountFiles($dir)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - GetCountFiles from $dir");
		
		$dir_array = array();
		
		$this->GetFiles($dir, $dir_array);
		
		Core\CoreCommons\Logger::Debug("Number of documents : " . count($dir_array));
		
		return count($dir_array);
	}
	
	/**
	 * Recursive function to return a multidimensional array of folders and files
	 *
	 * @param string $dir The directory path
	 * @param string $documents  The array of folders and files
	 * @param string $parent The parent directory
	 * 
	 * @return array List of folders
	 */
	public function GetFilesRecursiveToDocuments($dir, &$documents, $parent = null)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - GetFiles from $dir with actual documents parsed : ". count($documents));
		
		// Create array of current directory
		//$files = preg_grep('/^([^.])/', scandir($dir));
		
		$files = array();
		$handle = opendir($dir);
		while (false !== ($file = readdir($handle))) 
		{
			if ($file != "." && $file != "..")
			{
				$files[] = $file;
			}
		}
		
		//Ignore hidden files
		$files = preg_grep('/^([^.])/', $files);
		
		foreach($files as $val)
		{
			// If directory then dive deeper, else add file to directory key
			if(is_dir($dir.'/'.$val))
			{
				// Add value to current array, dir or file
				$document = null;
				if($parent == null)
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir.'/'.$val), true);
				}
				else
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir.'/'.$val), true, $parent->Id);
				}
				
				array_push($documents, $document);
				
				//Reset the timeout script execution
				set_time_limit(5);
				
				$this->GetFilesToDocuments($dir.'/'.$val, $documents, $document);
			}
			else
			{
				$document = null;
				
				if($parent == null)
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir), false);
				}
				else
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir), false, $parent->Id);
				}

				array_push($documents, $document);
			}
		}
	}
	
	/**
	 * Recursive function to return a multidimensional array of folders and files
	 *
	 * @param string $dir The directory path
	 * @param string $documents  The array of folders and files
	 * @param string $parent The parent directory
	 * 
	 * @return array List of folders
	 */
	public function GetFilesToDocuments($dir, &$documents, $parent = null)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - GetFiles from $dir with actual documents parsed : ". count($documents));
		
		$files = array();
		$handle = opendir($dir);
		while (false !== ($file = readdir($handle))) 
		{
			if ($file != "." && $file != "..")
			{
				$files[] = $file;
			}
		}
		
		//Ignore hidden files
		$files = preg_grep('/^([^.])/', $files);
		
		foreach($files as $val)
		{
			// If directory then dive deeper, else add file to directory key
			if(is_dir($dir.'/'.$val))
			{
				// Add value to current array, dir or file
				$document = null;
				if($parent == null)
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir.'/'.$val), true);
				}
				else
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir.'/'.$val), true, $parent->Id);
				}
				
				array_push($documents, $document);
			}
			else
			{
				$document = null;
				
				if($parent == null)
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir), false);
				}
				else
				{
					$document = Core\CoreContracts\Document::Create(count($documents), utf8_encode($val), utf8_encode($dir), false, $parent->Id);
				}

				array_push($documents, $document);
			}
		}
	}
	
	/**
	 * Get all folders list
	 *
	 * @param string $rootPath The directory path
	 * @param array $dir_array The array directories
	 * 
	 * @return array List of folders
	 */
	public function GetFolders($rootPath, &$dir_array)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - GetFolders from $rootPath");
		
		// Create array of current directory
		$files = preg_grep('/^([^.])/', scandir($rootPath));
	    
		if(is_array($files))
		{
			foreach($files as $val)
			{
				// Skip home and previous listings
				if($val == '.' || $val == '..')
				{
					continue;
				}
			   
				// If directory then dive deeper, else add file to directory key
				if(is_dir($rootPath . $val))
				{
					// Add folder name value to current array
					array_push($dir_array, $rootPath . $val);

					$this->GetFolders($rootPath . $val, $dir_array);
				}
				else
				{
					continue;
				}
			}
		}
		ksort($dir_array);
	}
	
	/**
	 * Upload a file from temp path to a target dir
	 *
	 * @param string $tempPath The temporary directory
	 * @param array $dirPath The directory path
	 * @param array $dirPath The file name
	 * 
	 * @return Document The uploaded document
	 */
	public function Upload($tempPath, $dirPath, $filename)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - Upload $tempPath, $dirPath, $filename");
		
		if(!is_dir($dirPath))
		{
			Core\CoreCommons\Logger::Info("FileSystemHelpers - $dirPath doesn't exist");
			
			mkdir($dirPath);
		}
		
		$targetDir = $dirPath . DIRECTORY_SEPARATOR . $filename;

		return move_uploaded_file($tempPath, $targetDir);
	}

	/**
	 * Delete a document, it can be a folder or a file
	 *
	 * @param string $path The path of the document to delete
	 * 
	 * @return Document The deleted document
	 */
	public function Delete($path)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - Delete $path");
		
		$result = false;
		if(is_dir($path))
		{
			Core\CoreCommons\Logger::Info("FileSystemHelpers - $path is a directory");
			$result = $this->deleteDirectory($path);
		}
		else
		{
			Core\CoreCommons\Logger::Info("FileSystemHelpers - $path is a file");
			$result = unlink($path);
		}
		
		return $result;
	}
	
	/**
	 * Delete a directory
	 *
	 * @param string $dir The path of the directory to delete
	 * 
	 * @return Document The deleted directory
	 */
	private function deleteDirectory($dir) 
	{
		if (!file_exists($dir)) {
			return true;
		}

		if (!is_dir($dir)) {
			return unlink($dir);
		}

		foreach (scandir($dir) as $item) {
			if ($item == '.' || $item == '..') {
				continue;
			}
			if (!$this->deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
				return false;
			}
		}

		return rmdir($dir);
	}
	
	/**
	 * Rename a document : directory or file
	 *
	 * @param string $path The path of the document to rename
	 * @param string $newName The new name of the document
	 * @param string $oldName  The old name of the document
	 * 
	 * @return Document The deleted directory
	 */
	public function Rename($path, $newName, $oldName)
	{
		Core\CoreCommons\Logger::Info("FileSystemHelpers - Rename $path, $newName, $oldName");
		
		$result = false;
		
		$oldPath = $path . DIRECTORY_SEPARATOR . $oldName;
		$newPath = $path . DIRECTORY_SEPARATOR . $newName;
		$result = rename($oldPath, $newPath);
		
		return $result;
	}

	/**
	 * Copy a directory or a file
	 *
	 * @param string $src It's the source to copy
	 * @param string $dst It's the destination
	 * 
	 * @return Document The copy document
	 */
	public function Copy($src, $dst)
	{
		if($src != null && $src != '' && $dst != null && $dst != '')
		{
			if(is_dir($src))
			{
				$dir = opendir($src);
				@mkdir($dst);
				while(false !== ( $file = readdir($dir)) ) 
				{
					if (( $file != '.' ) && ( $file != '..' )) 
					{
						//Reset the timeout script execution
						set_time_limit(5);
						if ( is_dir($src . '/' . $file) ) 
						{
							$this->Copy($src . '/' . $file,$dst . '/' . $file);
						}
						else 
						{
							copy($src . '/' . $file, $dst . '/' . $file);
						}
					}
				}
				closedir($dir);
			}
			else
			{
				copy($src, $dst);
			}
		}
	}
	
	/**
	 * Create a directory
	 *
	 * @param string $path The directory path to create
	 * 
	 * @return Document The created directory
	 */
	public function CreateDirectory($path)
	{
		return mkdir($path);
	}
	
	/*
	* Delete all accent from string
	*
	* @param string $str The str to delete accents
	*
	* @return string The string without accent
	*/
	public function RemoveAccent($str)
	{
		$a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð',
					'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã',
					'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ',
					'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ',
					'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę',
					'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī',
					'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'Ĳ', 'ĳ', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ',
					'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ŉ', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ',
					'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 
					'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 
					'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ',
					'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');

		$b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O',
					'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c',
					'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u',
					'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D',
					'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g',
					'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K',
					'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o',
					'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S',
					's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W',
					'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i',
					'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
		return str_replace($a, $b, $str);
	} 

}

?> 